perm filename TFTOPL.SAI[MF,DEK] blob
sn#554419 filedate 1981-01-08 generic text, type T, neo UTF8
begin "tftopl" comment PL file maker;
comment
edited by Ramshaw, December 10, 1980 9:40 PM
changed names of codingschemes as per request of DEK
edited by Ramshaw, November 13, 1980 10:38 AM
changed to scalable TFM format, and corresponding PL
allow eight bit character codes
edited by Knuth, December 13, 1979
added "extraspace" parameter
edited by Wyatt, September 4, 1979 8:10 AM
new PL format
edited by Wyatt, May 5, 1979 12:38 PM
derives family name from input file name
edited by Wyatt, April 27, 1979 3:04 PM
now understands special math font info in sy and ex fonts
edited by Wyatt, September 27, 1978 4:15 PM
changes for new TFP file format
edited by Guibas, August 29, 1978 5:06 PM;
require "⊂⊃⊂⊃" delimiters;
DEFINE WAITS=TRUE, TENEX=FALSE;
define #=⊂;comment ⊃;
define thru=⊂step 1 until⊃;
define crlf=⊂('15&'12)⊃;
define DEBUG=⊂comment⊃ # change to ⊂comment⊃ for debugged version;
define simp=⊂simple⊃;
define saf=⊂safe⊃;
DEBUG redefine simp=⊂⊃;
DEBUG redefine safe=⊂⊃;
integer ochan;
IFC WAITS THENC
integer count, brchar, eof, ocount, obrchar, oeof;
ENDC
define Ws(s)=⊂cprint(ochan, s)⊃;
define Wr(n)=⊂cprint(ochan, " R ",n)⊃;
define Wd(n)=⊂cprint(ochan, " D ",n)⊃;
define Wo(n)=⊂cprint(ochan, " O ",cvos(n))⊃;
define Wx(n)=⊂cprint(ochan, " R ",cvf((n ash -4)/(2↑20)))⊃;
define printable(char)=⊂(not extfont) and
((("0"≤char) and (char≤"9")) or (("A"≤char) and (char≤"Z")) or
(("a"≤char) and (char≤"z")))⊃;
define WChar(char)=⊂if printable(char)
then cprint(ochan, " C "&char) else Wo(char)⊃;
integer chan, lev; string fonttype; boolean symbolfont, extfont;
boolean sevenbitsafe,sevenbitsafeclaim;
comment offsets in header array;
define
checksumofst=0,
designsizeofst=1,
codingschemeofst=2,
familyofst=12,
randomofst=17;
comment sizes and positions of fields in finfo;
define wds=8, hts=4, dps=4, ics=6, tgs=2, rems=8;
define remd=4;
define tgd=remd+rems, icd=tgd+tgs, dpd=icd+ics, htd=dpd+dps, wdd=htd+hts;
comment sizes and positions of fields in ligkern program;
define lsbs=1, unused1s=7, lncs=8, ltgs=1, unused2s=7, lrems=8;
define lremd=4;
define ltgd=lremd+lrems+unused2s, lncd=ltgd+ltgs, lsbd=lncd+lncs+unused1s;
define tagnone=0, taglig=1, taglist=2, tagvar=3;
define ligstep=0, kernstep=1;
define fs(f)=⊂f⊃&"s";
define fd(f)=⊂f⊃&"d";
define field(f,x)=⊂(((x)lsh -fd(f))land(2↑fs(f)-1))⊃;
define lefthalf(x)=⊂(x lsh -20)⊃;
define righthalf(x)=⊂((x lsh -4)land((1 lsh 16) -1))⊃;
preload_with "SLANT","SPACE","STRETCH","SHRINK","XHEIGHT","QUAD";
string array pnames[1:6];
preload_with "NUM1","NUM2","NUM3","DENOM1","DENOM2","SUP1","SUP2","SUP3",
"SUB1","SUB2","SUPDROP","SUBDROP","DELIM1","DELIM2","AXISHEIGHT";
string array snames[8:22];
preload_with "DEFAULTRULETHICKNESS","BIGOPSPACING1","BIGOPSPACING2",
"BIGOPSPACING3","BIGOPSPACING4","BIGOPSPACING5";
string array enames[8:13];
preload_with "TOP","MID","BOT","EXT";
string array xnames[1:4];
external procedure bail;
simp procedure cr;
begin
integer i;
cprint(ochan,crlf);
for i←1 thru lev do cprint(ochan, " ");
end;
simp procedure bg;
begin
cprint(ochan, "(");
lev←lev+1;
end;
simp procedure ndd;
begin
lev←lev-1;
cprint(ochan, ")"); cr;
end;
simp string procedure getBCPL(integer ptr);
begin
integer i,len,bp; string res;
bp←point(8,memory[ptr],-1);
len←ildb(bp); res←null;
for i←1 thru len do res←res&(ildb(bp));
return(res);
end;
simp string procedure decodeface(integer f);
begin
integer w,s,e # weight, slope, expansion;
s←case f mod 2 of ("R","I");
f←f div 2;
w←case f mod 3 of ("M","B","L");
f←f div 3;
e←case f mod 3 of ("R","C","E");
return(w&s&e);
end;
simp string procedure getface(integer f);
begin
f←f land '377;
if f≥18 then return(" O "&cvos(f))
else return(" F "&decodeface(f));
end;
procedure doit;
begin "doit"
integer lf,lh,bc,ec,nw,nh,nd,ni,nl,nk,ne,np,data;
data←wordin(chan);
lf←lefthalf(data); lh←righthalf(data);
data←wordin(chan);
bc←lefthalf(data); ec←righthalf(data);
data←wordin(chan);
nw←lefthalf(data); nh←righthalf(data);
data←wordin(chan);
nd←lefthalf(data); ni←righthalf(data);
data←wordin(chan);
nl←lefthalf(data); nk←righthalf(data);
data←wordin(chan);
ne←lefthalf(data); np←righthalf(data);
begin "dynamic array allocate"
comment All these arrays are one word longer than necessary,
since SAIL won't allow you to declare an empty array!;
integer array header[0:lh];
saf integer array finfo[bc:ec+1];
integer array charwd[0:nw];
integer array charht[0:nh];
integer array chardp[0:nd];
integer array charic[0:ni];
integer array ligkern[0:nl];
integer array kern[0:nk];
integer array ext[0:ne];
integer array fontpar[1:np+1];
procedure doparams;
begin "doparams"
integer i;
for i←1 thru 6 do
begin
bg; Ws(pnames[i]); Wx(fontpar[i]); ndd;
end;
bg; Ws(if symbolfont then "MATHSPACE" else "EXTRASPACE");
Wx(fontpar[7]); ndd;
if symbolfont then
for i←8 thru 22 do
begin bg; Ws(snames[i]); Wx(fontpar[i]); ndd end
else if extfont then
for i←8 thru 13 do
begin bg; Ws(enames[i]); Wx(fontpar[i]); ndd end;
end "doparams";
procedure dolabels(integer i);
begin integer c;
for c←bc thru ec do
if field(tg,finfo[c])=taglig and
field(rem,finfo[c])=i then
begin bg; Ws("LABEL"); WChar(c); ndd end;
end;
boolean procedure dolig(integer lgindex);
comment returns stop bit as value;
begin integer lgentry, nxtchar, rem;
lgentry←ligkern[lgindex];
nxtchar ← field(lnc,lgentry);
rem ← field(lrem,lgentry);
case field(ltg,lgentry) of
begin
[ligstep]
begin
bg; Ws("LIG"); WChar(nxtchar); WChar(rem); ndd;
end;
[kernstep]
begin
bg; Ws("KRN"); WChar(nxtchar); Wx(kern[rem]); ndd;
end
end;
return(field(lsb,lgentry));
end;
procedure doligtable;
begin integer lgindex;
if nl=0 then return # empty ligtable;
bg; Ws("LIGTABLE"); cr;
for lgindex←0 thru nl-1 do
begin
dolabels(lgindex);
if dolig(lgindex) then
begin bg; Ws("STOP"); ndd end;
end;
ndd;
end;
procedure dovarchar(integer vcentry);
begin integer j,ecd;
comment extensible character;
define ecs=8;
ecd←36 # bitsperwd;
bg; Ws("VARCHAR"); cr;
for j←1 thru 4 do
begin integer c;
ecd←ecd-ecs; c←field(ec,vcentry);
if c neq 0 then
begin bg; Ws(xnames[j]); WChar(c); ndd end;
end;
ndd;
end;
boolean procedure unsafevarchar(integer vcentry);
begin integer j,ecd;
define ecs=8;
ecd←36 # bitsperwd;
for j←1 thru 4 do
begin integer c;
ecd←ecd-ecs; c←field(ec,vcentry);
if c≥'200 then return(true);
end;
return(false);
end;
boolean procedure checksafe;
begin
comment this procedure computes from the basic TFM
data whether or not the file is sevenbitsafe;
integer char,lig;
for char←bc thru (ec min '177) do
case field(tg,finfo[char]) of
begin
[tagnone] ;
[taglig]
begin integer l, step, nxtchar, rem;
l←field(rem,finfo[char]);
while true do
begin
step←ligkern[l];
nxtchar←field(lnc,step);
rem←field(lrem,step);
if nxtchar<'200 and field(ltg,step)=ligstep
and rem≥'200 then return(false);
if field(lsb,step) then done;
l←l+1;
end;
end;
[tagvar] if unsafevarchar(ext[field(rem,finfo[char])]) then
return(false);
[taglist] if field(rem,finfo[char])≥'200 then return(false)
end;
return(true);
end;
integer char;
comment *** Read in the data of the .tfm file ***;
arryin(chan,header[0],lh);
arryin(chan,finfo[bc],ec-bc+1);
arryin(chan,charwd[0],nw);
arryin(chan,charht[0],nh);
arryin(chan,chardp[0],nd);
arryin(chan,charic[0],ni);
arryin(chan,ligkern[0],nl);
arryin(chan,kern[0],nk);
arryin(chan,ext[0],ne);
arryin(chan,fontpar[1],np);
lev←0;
sevenbitsafe←checksafe;
comment Output header data;
bg; Ws("FAMILY "); Ws(getBCPL(location(header[familyofst]))); ndd;
bg; Ws("FACE "); Ws(getface(header[randomofst] lsh -4)); ndd;
fonttype←getBCPL(location(header[codingschemeofst]));
symbolfont←equ(fonttype,"TEX MATHSY");
extfont←equ(fonttype,"TEX MATHEX");
bg; Ws("CODINGSCHEME "); Ws(fonttype); ndd;
bg; Ws("CHECKSUM "); Wo(header[checksumofst] lsh -4); ndd;
bg; Ws("DESIGNSIZE "); Wx(header[designsizeofst]); ndd;
sevenbitsafeclaim←if header[randomofst]<0 then true else false;
bg; Ws("SEVENBITSAFEFLAG "); if sevenbitsafeclaim then
Ws("TRUE") else Ws("FALSE"); ndd;
if sevenbitsafe and not sevenbitsafeclaim then
begin bg; Ws("COMMENT This font actually is seven bit safe.");
ndd; end;
if not sevenbitsafe and sevenbitsafeclaim then
begin bg;
Ws("COMMENT Danger! This font is NOT actually seven bit safe!");
ndd; end;
bg; Ws("UNITS EMS"); ndd;
bg; Ws("TEXINFO"); cr; doparams; ndd;
doligtable;
for char ← bc thru ec do
begin integer index,charinfo;
define code(x)=⊂field(x,charinfo)⊃;
charinfo←finfo[char];
if charinfo=0 then continue # non-existent character;
print(" ",cvos(char));
bg; Ws("CHARACTER"); WChar(char); cr;
index ← code(wd);
bg; Ws("CHARWD"); Wx(charwd[index]); ndd;
index ← code(ht);
bg; Ws("CHARHT"); Wx(charht[index]); ndd;
index ← code(dp);
bg; Ws("CHARDP"); Wx(chardp[index]); ndd;
index ← code(ic);
if index≠0 then
begin bg; Ws("CHARIC"); Wx(charic[index]); ndd; end;
case code(tg) of
begin
[tagnone] ;
[taglig]
begin integer l;
l←code(rem);
bg; Ws("COMMENT"); cr;
while not dolig(l) do l←l+1;
ndd;
end;
[tagvar] dovarchar(ext[code(rem)]);
[taglist]
begin bg; Ws("NEXTLARGER"); WChar(code(rem)); ndd; end
end;
ndd # of CHARACTER;
end;
end "dynamic array allocate";
end "doit";
boolean procedure openinputfile;
begin "openinputfile"
string name; integer i, c; string array namef[1:3];
external integer !skip!;
while true do
begin
print("TFM input file: ");
IFC TENEX THENC
release(chan) # close old input if any;
chan←gtjfnl(null,'100100000000,'000100000101,
null,null,null,"TFM",null,null,0);
if !skip!≠0 then
begin print(crlf, "What?", crlf); continue end;
openf(chan,2);
if !skip!≠0 then
begin print(crlf, "Can't open that file!", crlf);
continue end;
ENDC
IFC WAITS THENC
open(chan←getchan,"DSK",8,19,0,count,brchar,eof);
open(ochan←getchan,"DSK",0,0,19,ocount,obrchar,oeof);
name←inchwl;
namef[1]←namef[2]←namef[3]←"";
i←1;
while c←lop(name) do begin
if c="." then i←2
else if c="[" then i←3;
namef[i]←namef[i]&c;
end;
if namef[2]="" then namef[2]←".TFM";
if namef[3]="" then name←namef[1]&namef[2]&"[TEX,SYS]"
else name←namef[1]&namef[2]&namef[3];
lookup(chan,name,eof);
if eof then begin
print(crlf, "Can't open ",name,crlf); continue end;
name←namef[1]&".PL"&namef[3];
enter(ochan,name,oeof);
if oeof then begin
print(crlf, "Can't open ",name,crlf); continue end;
ENDC
return(true)
end;
end "openinputfile";
comment Main code starts here;
print("TFTOPL of December 10, 1980",crlf);
IFC WAITS THENC
openinputfile;
doit;
print(crlf);
release(chan); release(ochan);
ENDC
IFC TENEX THENC
while openinputfile do
do begin
string filename, outfilename;
filename←jfns(chan, '001000000000) # name part only, not extension;
outfilename←filename&".PL";
ochan←openfile(outfilename,"WA");
print(crlf,"PL output file: ",jfns(ochan,0),crlf);
doit;
release(ochan);
print(crlf);
end until not indexfile(chan);
ENDC
end "tftopl";